using HslCommunication.BasicFramework;
using HslCommunication.Core;
using HslCommunication.Serial;

namespace HslCommunication.Profinet.Keyence
{
	/// <summary>
	/// 基恩士KV上位链路串口通信的对象,适用于Nano系列串口数据,KV1000以及L20V通信模块，地址格式参考api文档<br />
	/// Keyence KV upper link serial communication object, suitable for Nano series serial data, and L20V communication module, please refer to api document for address format
	/// </summary>
	/// <remarks>
	/// <inheritdoc cref="T:HslCommunication.Profinet.Keyence.KeyenceNanoSerialOverTcp" path="remarks" />
	/// </remarks>
	public class KeyenceNanoSerial : SerialDeviceBase
	{
		/// <summary>
		/// 实例化基恩士的串口协议的通讯对象<br />
		/// Instantiate the communication object of Keyence's serial protocol
		/// </summary>
		public KeyenceNanoSerial()
		{
			base.ByteTransform = new RegularByteTransform();
			base.WordLength = 1;
		}

		/// <inheritdoc />
		protected override OperateResult InitializationOnOpen()
		{
			OperateResult<byte[]> operateResult = ReadBase(KeyenceNanoSerialOverTcp.ConnectCmd);
			if (!operateResult.IsSuccess)
			{
				return operateResult;
			}
			if (operateResult.Content.Length > 2 && operateResult.Content[0] == 67 && operateResult.Content[1] == 67)
			{
				return OperateResult.CreateSuccessResult();
			}
			return new OperateResult("Check Failed: " + SoftBasic.ByteToHexString(operateResult.Content, ' '));
		}

		/// <inheritdoc />
		protected override OperateResult ExtraOnClose()
		{
			OperateResult<byte[]> operateResult = ReadBase(KeyenceNanoSerialOverTcp.DisConnectCmd);
			if (!operateResult.IsSuccess)
			{
				return operateResult;
			}
			if (operateResult.Content.Length > 2 && operateResult.Content[0] == 67 && operateResult.Content[1] == 70)
			{
				return OperateResult.CreateSuccessResult();
			}
			return new OperateResult("Check Failed: " + SoftBasic.ByteToHexString(operateResult.Content, ' '));
		}

		/// <inheritdoc />
		public override OperateResult<byte[]> Read(string address, ushort length)
		{
			OperateResult<byte[]> operateResult = KeyenceNanoSerialOverTcp.BuildReadCommand(address, length);
			if (!operateResult.IsSuccess)
			{
				return OperateResult.CreateFailedResult<byte[]>(operateResult);
			}
			OperateResult<byte[]> operateResult2 = ReadBase(operateResult.Content);
			if (!operateResult2.IsSuccess)
			{
				return OperateResult.CreateFailedResult<byte[]>(operateResult2);
			}
			OperateResult operateResult3 = KeyenceNanoSerialOverTcp.CheckPlcReadResponse(operateResult2.Content);
			if (!operateResult3.IsSuccess)
			{
				return OperateResult.CreateFailedResult<byte[]>(operateResult3);
			}
			OperateResult<string, int> operateResult4 = KeyenceNanoSerialOverTcp.KvAnalysisAddress(address);
			if (!operateResult4.IsSuccess)
			{
				return OperateResult.CreateFailedResult<byte[]>(operateResult4);
			}
			return KeyenceNanoSerialOverTcp.ExtractActualData(operateResult4.Content1, operateResult2.Content);
		}

		/// <inheritdoc />
		public override OperateResult Write(string address, byte[] value)
		{
			OperateResult<byte[]> operateResult = KeyenceNanoSerialOverTcp.BuildWriteCommand(address, value);
			if (!operateResult.IsSuccess)
			{
				return operateResult;
			}
			OperateResult<byte[]> operateResult2 = ReadBase(operateResult.Content);
			if (!operateResult2.IsSuccess)
			{
				return operateResult2;
			}
			OperateResult operateResult3 = KeyenceNanoSerialOverTcp.CheckPlcWriteResponse(operateResult2.Content);
			if (!operateResult3.IsSuccess)
			{
				return operateResult3;
			}
			return OperateResult.CreateSuccessResult();
		}

		/// <inheritdoc />
		public override OperateResult<bool[]> ReadBool(string address, ushort length)
		{
			OperateResult<byte[]> operateResult = KeyenceNanoSerialOverTcp.BuildReadCommand(address, length);
			if (!operateResult.IsSuccess)
			{
				return OperateResult.CreateFailedResult<bool[]>(operateResult);
			}
			OperateResult<byte[]> operateResult2 = ReadBase(operateResult.Content);
			if (!operateResult2.IsSuccess)
			{
				return OperateResult.CreateFailedResult<bool[]>(operateResult2);
			}
			OperateResult operateResult3 = KeyenceNanoSerialOverTcp.CheckPlcReadResponse(operateResult2.Content);
			if (!operateResult3.IsSuccess)
			{
				return OperateResult.CreateFailedResult<bool[]>(operateResult3);
			}
			OperateResult<string, int> operateResult4 = KeyenceNanoSerialOverTcp.KvAnalysisAddress(address);
			if (!operateResult4.IsSuccess)
			{
				return OperateResult.CreateFailedResult<bool[]>(operateResult4);
			}
			return KeyenceNanoSerialOverTcp.ExtractActualBoolData(operateResult4.Content1, operateResult2.Content);
		}

		/// <inheritdoc />
		public override OperateResult Write(string address, bool value)
		{
			OperateResult<byte[]> operateResult = KeyenceNanoSerialOverTcp.BuildWriteCommand(address, value);
			if (!operateResult.IsSuccess)
			{
				return operateResult;
			}
			OperateResult<byte[]> operateResult2 = ReadBase(operateResult.Content);
			if (!operateResult2.IsSuccess)
			{
				return operateResult2;
			}
			OperateResult operateResult3 = KeyenceNanoSerialOverTcp.CheckPlcWriteResponse(operateResult2.Content);
			if (!operateResult3.IsSuccess)
			{
				return operateResult3;
			}
			return OperateResult.CreateSuccessResult();
		}

		/// <inheritdoc />
		public override string ToString()
		{
			return $"KeyenceNanoSerial[{base.PortName}:{base.BaudRate}]";
		}
	}
}
